package gfx;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

import util.VertexBuffer;
import android.graphics.PointF;
import android.util.FloatMath;

public class Shapes {
	
	static float verts[];
	static float theta; 
	static float c;
	static float s;
	static float t;
	static float x;
	static float y;
	static float[] square = new float[12];
	static float[] colors = new float[16];
    FloatBuffer colorBuffer;
    static FloatBuffer fb;
    static ByteBuffer bb;
	
	public static void drawSquare(GL10 gl, PointF topRight, PointF bottomLeft, float r, float g, float b, float a){
		
		square[0] = bottomLeft.x;
		square[1] = bottomLeft.y;
		square[2] = 0;
		square[3] = topRight.x;
		square[4] = bottomLeft.y;
		square[5] = 0;
		square[6] = bottomLeft.x;
		square[7] = topRight.y;
		square[8] = 0;
		square[9] = topRight.x;
		square[10] = topRight.y;
		square[11] = 0;
		
		Shapes.drawSquare(gl, square, r, g, b, a);
	}
	
	public static void drawSquare(GL10 gl, PointF loc, float halfWidth, float r, float g, float b, float a){
		
		square[0] = loc.x - halfWidth;
		square[1] = loc.y - halfWidth;
		square[2] = 0;
		square[3] = loc.x + halfWidth;
		square[4] = loc.y - halfWidth;
		square[5] = 0;
		square[6] = loc.x - halfWidth;
		square[7] = loc.y + halfWidth;
		square[8] = 0;
		square[9] = loc.x + halfWidth;
		square[10] = loc.y + halfWidth;
		square[11] = 0;
		
		Shapes.drawSquare(gl, square, r, g, b, a);
	}
	
	public static void drawSquare(GL10 gl, float x, float y, float halfWidth, float halfHeight, float r, float g, float b, float a){
		
		square[0] = x - halfWidth;
		square[1] = y - halfHeight;
		square[2] = 0;
		square[3] = x + halfWidth;
		square[4] = y - halfHeight;
		square[5] = 0;
		square[6] = x - halfWidth;
		square[7] = y + halfHeight;
		square[8] = 0;
		square[9] = x + halfWidth;
		square[10] = y + halfHeight;
		square[11] = 0;
		
		Shapes.drawSquare(gl, square, r, g, b, a);
	}
	
	public static void drawSquare(GL10 gl, float[] box, float r, float g, float b, float a){
		gl.glPushMatrix();
		gl.glDisable(GL10.GL_TEXTURE_2D);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glFrontFace(GL10.GL_CCW);
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, VertexBuffer.getVertexBuffer(box));
		gl.glColor4f(r, g, b, a);
		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, box.length / 3);
		gl.glColor4f(1, 1, 1, 1);
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glPopMatrix();
	}
	
	public static void drawHorizontalGradiantSquare(GL10 gl, float x, float y, float halfWidth, float halfHeight, float startR, float startG, float startB, float startA, float endR, float endG, float endB, float endA){		
	    colors = new float[]{
	    	startR, startG, startB, startA,
	    	endR, endG, endB, endA,
	    	startR, startG, startB, startA,
	    	endR, endG, endB, endA
	    };
		
		FloatBuffer colorBuffer = makeFloatBuffer(colors);
	    
		square[0] = x - halfWidth;
		square[1] = y - halfHeight;
		square[2] = 0;
		square[3] = x + halfWidth;
		square[4] = y - halfHeight;
		square[5] = 0;
		square[6] = x - halfWidth;
		square[7] = y + halfHeight;
		square[8] = 0;
		square[9] = x + halfWidth;
		square[10] = y + halfHeight;
		square[11] = 0;
		
		gl.glPushMatrix();
		gl.glDisable(GL10.GL_TEXTURE_2D);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glFrontFace(GL10.GL_CCW);
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, VertexBuffer.getVertexBuffer(square));

	    gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
	    gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
	    
		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, square.length / 3);
		
		gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glPopMatrix();
		
	}
	
	protected static FloatBuffer makeFloatBuffer(float[] arr) {
	    bb = ByteBuffer.allocateDirect(arr.length*4);
	    bb.order(ByteOrder.nativeOrder());
	    fb = bb.asFloatBuffer();
	    fb.put(arr);
	    fb.position(0);
	    return fb;
	}
	
	public static void drawCircle(GL10 gl, float radius, PointF loc, int detail, float r, float g, float b, float a){
		//if(verts.length != detail * 3) TODO:  save some stuff, so you won't have to recalc circle every draw
			
		verts = new float[detail * 3];
		theta = (float)((float)2 * 3.1415926) / ((float)detail); 
		c = FloatMath.cos(theta);//precalculate the sine and cosine
		s = FloatMath.sin(theta);

		x = radius;//we start at angle = 0 
		y = 0; 
	    
		for(int i = 0; i < detail * 3; i++) 
		{ 
			verts[i] =x + loc.x;
			verts[i+1] = y + loc.y;//output vertex 
			verts[i+2] = 0;
	        
			//apply the rotation matrix
			t = x;
			x = c * x - s * y;
			y = s * t + c * y;
			i+=2;
		} 
		
		gl.glPushMatrix();
		gl.glDisable(GL10.GL_TEXTURE_2D);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glFrontFace(GL10.GL_CW);
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, VertexBuffer.getVertexBuffer(verts));
		gl.glColor4f(r, g, b, a);
		gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, verts.length / 3);
		gl.glColor4f(1, 1, 1, 1);
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glPopMatrix();

	}
	
	public static void drawVarianceArc(GL10 gl, float radius, float locX, float locY, int detail, float angle, float variance, boolean dir, float r, float g, float b, float a){
//		if(dir)
			drawArc(gl, radius, locX, locY, detail, angle - variance, angle + variance, dir, r, g, b, a, true);
//		else {
//			drawArc(gl, radius, locX, locY, detail, angle - variance, angle + variance, dir, r, g, b, a);
//		}
	}
	
	public static void drawArc(GL10 gl, float radius, float locX, float locY, int detail, float angleStart, float angleStop, boolean dir, float r, float g, float b, float a, boolean var) {
		verts = new float[(detail+2) * 3];
		theta = (float) (((float)2 * 3.1415926)/ ((float)detail));
		c = FloatMath.cos(theta/((float) 360/(angleStop - angleStart)));//precalculate the sine and cosine
		s = FloatMath.sin(theta/((float) 360/(angleStop - angleStart)));

		x = radius;//we start at angle = 0 
		y = 0; 
		

	    verts[0] = verts[1] = verts[2] = 0;
	    
		for(int i = 3; i < (detail+2) * 3; ++i) 
		{ 
			verts[i] = x;
			verts[i+1] = y;//output vertex 
			verts[i+2] = 0;
	        
			//apply the rotation matrix
			t = x;
			x = c * x - s * y;
			y = s * t + c * y;
			i+=2;
		}  
		
		gl.glPushMatrix();
		gl.glTranslatef(locX, locY, 0);
		if(!dir){
			gl.glScalef(-1, 1, 1);
		}
		gl.glRotatef(angleStart, 0, 0, 1);
		gl.glDisable(GL10.GL_TEXTURE_2D);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, VertexBuffer.getVertexBuffer(verts));
		gl.glColor4f(r, g, b, a);
		gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, verts.length / 3);
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glPopMatrix();
	}

	public static void drawArc(GL10 gl, float segments, float angle_start, float angle_stop) {
		int startAngle = 0;
		int endAngle = 90;
		float[] verts = new float[(endAngle - startAngle) * 3];
	    for(int angle=startAngle, i = 0; angle<=endAngle; ++angle){
	        verts[i] = (float)Math.cos(angle);
	        verts[++i] = (float)Math.sin(angle);
	        verts[++i] = 0;
	    }	
	    
		gl.glPushMatrix();
		gl.glTranslatef(3, 5, 0);
		gl.glDisable(GL10.GL_TEXTURE_2D);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glFrontFace(GL10.GL_CW);
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, VertexBuffer.getVertexBuffer(verts));
//		gl.glColor4f(r, g, b, a);
		gl.glColor4f(1, 0, 0, .5f);
		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, verts.length / 3);
//		gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, arc_vertices.length / 3);
		gl.glColor4f(1, 1, 1, 1);
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glPopMatrix();
	}

	public static void drawTriangle(GL10 gl, float[] points, float r, float g, float b , float a){
		gl.glPushMatrix();
		gl.glDisable(GL10.GL_TEXTURE_2D);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glFrontFace(GL10.GL_CW);
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, VertexBuffer.getVertexBuffer(points));
		gl.glColor4f(r, g, b, a);
		gl.glDrawArrays(GL10.GL_TRIANGLES, 0, points.length / 3);
		gl.glColor4f(1, 1, 1, 1);
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glPopMatrix();
	}


}
